package com.insist.util.aliyun;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;


public abstract class OSSObjectUtilBase {

    protected static Logger logger = LoggerFactory.getLogger(OSSObjectUtilBase.class);

    protected String bucketName = null;

    protected OSSClient client = null;

    protected OSSClient internalClient = null;

    private int URL_EFFECTIVE_TIME = 600000;

    protected final String MEDIA_JPG = "image/jpeg";


    protected static String ALIYUN_INTERNAL = Configure.getProperty("aliyun.inner");


    protected static String ALIYUN_OUTER = Configure.getProperty("aliyun.outer");


    protected static String ALIYUN_ECS = Configure.getProperty("aliyun.inner.ecs");



    protected OSSObjectUtilBase(String accessKeyID, String accessKeySecret, String bucketName) {
        this.bucketName = bucketName;
        this.client = new OSSClient(ALIYUN_OUTER,accessKeyID, accessKeySecret );
        if (ALIYUN_ECS.equals(1)) {
            logger.info("internalClient 阿里云内网");
            this.internalClient = new OSSClient(ALIYUN_INTERNAL, accessKeyID, accessKeySecret);
        } else {
            logger.info("client阿里云外网");
            this.internalClient = this.client;
        }
    }


    public boolean uploadFileSingle(String key, byte[] filebytes,String contentType) {
        try {
            logger.info("正在上传..key={},...size={},...bucketName={},...", key, filebytes.length,bucketName);
            // 上传流实现
            String md5 = DigestUtils.md5Hex(filebytes);
            PutObjectResult pr = uploadByStreamNew(key, filebytes, contentType);
            if (StringUtils.isNotBlank(md5) && pr != null && md5.equalsIgnoreCase(pr.getETag())) {
                logger.info("上传成功..key={},...size={},...bucketName={},...", key, filebytes.length,bucketName);
                return true;
            }
            logger.error("upload to aliyun failed key:{},md5:{},md5After:{}",key , md5 , (pr == null ? null : pr.getETag()));
            return false;
        } catch (Exception e) {
            logger.error("上传错误..key=" + key + ",...size=" + filebytes.length + ",...bucketName=" + bucketName + ",...", e);
            return false;
        }
    }


    public boolean uploadFileSingle(String key, byte[] filebytes) {
        return uploadFileSingle(key,filebytes,MEDIA_JPG);
    }




    // 下载文件2
    public byte[] downloadFile(String key) throws OSSException, ClientException, IOException {
        return IOUtils.toByteArray(this.getObject(key));
    }

    /**
     * 下载文件
     * 
     * @param key
     * @param fileName
     * @return
     */
    @Deprecated
    public File downloadFile(String key, String fileName) {
        File file = null;
        try {
            logger.info("正在下载..key={},...bucketName={},...{}", key, bucketName, fileName);
            file = downloadFile(internalClient, bucketName, key, fileName);
            logger.info("下载成功.." + fileName);
        } catch (Exception e) {
            logger.error("下载错误：", e);
        }
        return file;

    }

    /**
     * 根据key删除文件
     */
    public void deleteFile(String key) {
        logger.info("正在删除..bucketName={},key={}", bucketName, key);
        internalClient.deleteObject(bucketName, key);
        logger.info("删除成功..");
    }

    /**
     * 根据给定前缀 删除文件
     */
    public void deleteFile4prefix(String prefix) {
        // 构造ListObjectsRequest请求
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
        // 递归列出fun目录下的所有文件
        listObjectsRequest.setPrefix(prefix);
        ObjectListing listing = internalClient.listObjects(listObjectsRequest);
        // 遍历所有Object
        for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
            deleteFile(objectSummary.getKey());
        }
    }


    protected abstract PutObjectResult uploadByStreamNew(String key, byte[] fileBytes,String contentType)
            throws OSSException, ClientException, IOException;



    // 下载文件
    private File downloadFile(OSSClient client, String bucketName, String key, String filename)
            throws OSSException, ClientException {
        File file = new File(filename);
        client.getObject(new GetObjectRequest(bucketName, key), file);
        return file;
    }

    // 获得对象返回流
    public InputStream getObject(String key) throws IOException {
        // 获取Object的输入流
        return internalClient.getObject(bucketName, key).getObjectContent();
    }

    // 拷贝Object
    public void copyObject(String srcKey, String destKey) {
        // 拷贝Object
        internalClient.copyObject(bucketName, srcKey, bucketName, destKey);
    }

    // 剪切Object
    public void cutObject(String srcKey, String destKey) {
        // 拷贝Object
        logger.info("正在剪切..bucketName={},srcKey={},destKey={}", bucketName, srcKey, destKey);
        internalClient.copyObject(bucketName, srcKey, bucketName, destKey);
        internalClient.deleteObject(bucketName, srcKey);
        logger.info("剪切成功..");
    }

    // 动态地生成一个经过签名的URL
    public String getUrl(String key, int timeout) {
        return client.generatePresignedUrl(bucketName, key, new Date(new Date().getTime() + timeout)).toString();
    }

    /**
     * 得到暂时的http链接
     * 
     * @author fuhao
     * @param key
     * @return
     */
    public String getUrl(String key) {
        return getUrl(key, URL_EFFECTIVE_TIME);
    }
}
